// redis.service.ts
import { Injectable, Inject } from "@nestjs/common";
import { Redis } from "ioredis";

/**
 * Redis 服务类
 *
 * 提供 Redis 缓存的基本操作方法，包括设置、获取和删除键值对。
 * 该类封装了 IORedis 客户端，提供了简化的 Redis 操作接口。
 *
 * @example
 * ```typescript
 * // 在控制器或服务中注入使用
 * constructor(private readonly redisService: RedisService) {}
 *
 * // 设置键值
 * await this.redisService.set('user:1', 'John Doe');
 *
 * // 获取值
 * const value = await this.redisService.get('user:1');
 *
 * // 删除键
 * await this.redisService.del('user:1');
 * ```
 */
@Injectable()
export class RedisService {
  /**
   * 构造函数
   *
   * 通过依赖注入获取 Redis 客户端实例
   *
   * @param client - Redis 客户端实例，通过 "REDIS_CLIENT" token 注入
   */
  constructor(@Inject("REDIS_CLIENT") private readonly client: Redis) {}

  /**
   * 设置键值对
   *
   * 将指定的键和值存储到 Redis 中。如果键已存在，则会覆盖原有值。
   * 注意：如果 value 是对象，需要先序列化为字符串（如 JSON.stringify）。
   *
   * @param key - 要设置的键名
   * @param value - 要设置的值（字符串类型，如需存储对象请先序列化）
   * @returns Promise<void> 设置操作完成时解析
   *
   * @example
   * ```typescript
   * // 设置字符串值
   * await redisService.set('name', 'John');
   *
   * // 设置对象（需要序列化）
   * await redisService.set('user:1', JSON.stringify({ id: 1, name: 'John' }));
   * ```
   */
  async set(key: string, value: any): Promise<void> {
    await this.client.set(key, value);
  }

  /**
   * 获取键对应的值
   *
   * 从 Redis 中获取指定键的值。如果键不存在，则返回 null。
   *
   * @param key - 要获取的键名
   * @returns Promise<string | null> 返回键对应的值，如果键不存在则返回 null
   *
   * @example
   * ```typescript
   * // 获取值
   * const value = await redisService.get('name');
   * if (value) {
   *   console.log(value); // 输出: 'John'
   * }
   *
   * // 获取并解析 JSON 对象
   * const userJson = await redisService.get('user:1');
   * if (userJson) {
   *   const user = JSON.parse(userJson);
   * }
   * ```
   */
  async get(key: string): Promise<string | null> {
    return this.client.get(key);
  }

  /**
   * 设置键值对（带过期时间）
   *
   * 将指定的键和值存储到 Redis 中，并设置过期时间。
   *
   * @param key - 要设置的键名
   * @param value - 要设置的值（字符串类型，如需存储对象请先序列化）
   * @param ttl - 过期时间（秒）
   * @returns Promise<void> 设置操作完成时解析
   *
   * @example
   * ```typescript
   * // 设置带过期时间的值
   * await redisService.setWithTTL('token', 'abc123', 3600); // 1小时后过期
   * ```
   */
  async setWithTTL(key: string, value: any, ttl: number): Promise<void> {
    await this.client.setex(key, ttl, value);
  }

  /**
   * 删除一个或多个键
   *
   * 从 Redis 中删除指定的键。如果键不存在，则忽略该键。
   *
   * @param key - 要删除的键名
   * @returns Promise<number> 返回被删除键的数量（0 或 1）
   *
   * @example
   * ```typescript
   * // 删除单个键
   * const deleted = await redisService.del('user:1');
   * console.log(deleted); // 输出: 1（成功删除）或 0（键不存在）
   * ```
   */
  async del(key: string): Promise<number> {
    console.log(`del: ${key}`);
    return this.client.del(key);
  }
}
